package org.baicaixiaozhan.tenet.reflection;

import net.sf.cglib.proxy.Enhancer;
import org.baicaixiaozhan.tenet.reflection.aop.Advice;
import org.baicaixiaozhan.tenet.reflection.aop.interceptor.SimpleCglibInterceptor;
import org.baicaixiaozhan.tenet.reflection.aop.interceptor.SimpleJdkInterceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * DESC:
 *
 * @author : baicaixiaozhan
 * @since : 1.0.0
 */
public class ProxyFactory {

    private ProxyFactory() {
        throw new AssertionError();
    }

    public static Object newProxy(Object target, InvocationHandler invocationHandler) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                invocationHandler);
    }

    public static Object newProxy(Object target, Advice advice) {
        Class<?> targetClass = target.getClass();
        Class<?> superclass = targetClass.getSuperclass();
        if (targetClass.isInterface()
                || superclass.isInterface()
                || superclass.getInterfaces().length > 0) {
            return ProxyFactory.newProxyWithJdk(target, advice);
        }
        return ProxyFactory.newProxyWithCglib(target, advice);
    }

    public static Object newProxy(Object target, Advice advice, Boolean enableCglib) {
        return enableCglib ? ProxyFactory.newProxyWithCglib(target, advice) :
                ProxyFactory.newProxyWithJdk(target, advice);
    }

    public static Object newProxyWithJdk(Object target, Advice advice) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new SimpleJdkInterceptor(target, advice));
    }

    public static Object newProxyWithCglib(Object target, Advice advice) {
        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(target.getClass().getClassLoader());
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new SimpleCglibInterceptor(advice));
        return enhancer.create();
    }

}
